<template>
    <div class="boxs">
        <el-card>
            <div slot="header" class="clearfix">
                <span>ImgFoodParse_Config</span>
            </div>
            <el-form class="demo-form-inline" :model="form" :rules="rules" ref="ruleForm">
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="addVersion" style="display: block;width: 100%;" label-position="top"
                            prop="prompt_test">
                            <el-button type="primary" @click="openAddVersion" icon="el-icon-plus">add</el-button>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="version" style="display: block;width: 100%;" label-position="top"
                            prop="prompt_test">
                            <el-select v-model="queryParams.version" @change="handleQuery">
                                <el-option v-for="item in versionList" :key="item.id" :label="item.name"
                                    :value="item.id"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="prompt" style="display: block;width: 100%;" label-position="top"
                            prop="prompt_test">
                            <el-input autosize type="textarea" v-model="form.prompt_test" placeholder="请输入提示词"
                                resize="none" />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item label="model" label-position="top" prop="model_test">
                            <div style="display: flex; align-items: center;">
                                <el-input v-model="form.model_test" placeholder="Ai 模型" />
                                <el-tooltip class="item" style="margin-left: 10px;" effect="dark" content="Ai 模型"
                                    placement="top-end">
                                    <i class="el-icon-info" style="cursor: pointer;"></i>
                                </el-tooltip>
                            </div>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="Temperature" label-position="top" prop="temperature_test">
                            <div style="display: flex; align-items: center;">
                                <el-input v-model="form.temperature_test" type="number" placeholder="通常在 0 到 1 之间" />
                                <el-tooltip class="item" style="margin-left: 10px;" effect="dark"
                                    content="控制生成文本的随机性。值越低，输出越确定；值越高，输出越随机。通常在 0 到 1 之间。" placement="top-end">
                                    <i class="el-icon-info" style="cursor: pointer;"></i>
                                </el-tooltip>
                            </div>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="Top P" label-position="top" prop="top_p_test">
                            <div style="display: flex; align-items: center;">
                                <el-input v-model="form.top_p_test" type="number" placeholder="请输入Top P" />
                                <el-tooltip class="item" style="margin-left: 10px;" effect="dark"
                                    content="核采样。与 temperature 类似，但通过考虑概率分布的累积来限制选择。值为 0.1 意味着只考虑概率前 10% 的标记。"
                                    placement="top-end">
                                    <i class="el-icon-info" style="cursor: pointer;"></i>
                                </el-tooltip>
                            </div>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item label="Frequency penalty" label-position="top" prop="frequency_penalty_test">
                            <div style="display: flex; align-items: center;">
                                <el-input v-model="form.frequency_penalty_test" type="number"
                                    placeholder="-2.0 到 2.0" />
                                <el-tooltip class="item" style="margin-left: 10px;" effect="dark"
                                    content="控制生成文本中重复词语的惩罚。值越高，重复词语的可能性越小。范围通常在 -2.0 到 2.0 之间。" placement="top-end">
                                    <i class="el-icon-info" style="cursor: pointer;"></i>
                                </el-tooltip>
                            </div>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="Top K" label-position="top" prop="frequency_penalty_test">
                            <div style="display: flex; align-items: center;">
                                <el-input v-model="form.top_k_test" type="number" />

                            </div>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="Max tokens" label-position="top" prop="max_tokens_test">
                            <div style="display: flex; align-items: center;">
                                <el-input v-model="form.max_tokens_test" type="number" placeholder="请输入最大令牌数" />
                                <el-tooltip class="item" style="margin-left: 10px;" effect="dark"
                                    content="限制生成文本的最大长度。这个值决定了 API 可以返回的最大标记数。" placement="top-end">
                                    <i class="el-icon-info" style="cursor: pointer;"></i>
                                </el-tooltip>
                            </div>
                        </el-form-item>
                    </el-col>
                </el-row>


                <el-row :gutter="20">
                    <el-col :span="12">
                        <el-form-item label="imageUrl" label-position="top" prop="imageUrlList">
                            <!-- 只允许上传图片，多选，显示缩略图 -->
                            <el-upload action="" list-type="picture-card" :file-list="imageFileList"
                                :before-upload="beforeUpload" :on-remove="removeFile" :on-change="onFileChange"
                                :auto-upload="false" multiple accept="image/*">
                                <i class="el-icon-plus"></i>
                            </el-upload>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row :gutter="20">
                    <el-col :span="24">
                        <el-form-item label="output_language" label-position="top">
                            <el-input autosize v-model="form.content" placeholder="content" />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <el-row :gutter="80">
                <el-col :span="8">
                    <el-button type="warning" :loading="bloading" @click="submitForm">运行</el-button>
                    <el-button type="primary" @click="submitForm1">更新至线上</el-button>
                </el-col>
            </el-row>
        </el-card>

        <el-dialog title="result" :visible.sync="dialogVisible" width="800px" :before-close="handleClose">
            <div>
                <v-md-preview :text="messageRes.content"></v-md-preview>
            </div>
        </el-dialog>
        <el-dialog title="addVersion" :visible.sync="dialogVisible1" width="500px" :before-close="handleClose1">
            <div style="padding: 20px 30px; padding-bottom: 0;">
                <el-form :model="form1" :rules="rules1" ref="ruleForm1">
                    <el-row>
                        <el-col :span="24">
                            <el-form-item label="addVersion" prop="version">
                                <el-input v-model="form1.version" placeholder="例:1.0.0" />
                            </el-form-item>
                        </el-col>
                    </el-row>
                </el-form>
            </div>
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible1 = false">{{ $t('review.close') }}</el-button>
                <el-button :type="'primary'" @click="affirm"
                    :loading="addLoading">{{ $t('review.confirm') }}</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
import {
    getImgFoodParseConfig,
    updateImgFoodParseConfig,
    updateImgFoodParseConfigHandel,
    getImgFoodParseVersionList,
    addImgFoodParseVersion,
    upload
} from "@/api/Recipe";
export default {
    name: "review",
    data() {
        return {
            imageFileList: [], // 绑定 el-upload 用的图片文件数组
            bloading: false,
            dialogVisible: false,
            dialogVisible1: false,
            addLoading: false,
            messageRes: {
                content: "",
            },

            form: {
                prompt_test: "",
                model_test: "",
                temperature_test: "",
                top_p_test: "",
                frequency_penalty_test: "",
                top_k_test: "",
                max_tokens_test: "",
                content: "",
                imageUrl: '',
                imageFiles:[]
            },
            form1: {
                version: "",
            },
            versionList: [],
            queryParams: {
                version: "",
            },
            rules: {
                prompt_test: [{ required: true, message: "请输入提示词", trigger: "blur" }],
                model_test: [{ required: true, message: "请输入模型", trigger: "blur" }],
                temperature_test: [{ required: true, message: "请输入温度", trigger: "blur" }],
                top_p_test: [{ required: true, message: "请输入Top P", trigger: "blur" }],
                frequency_penalty_test: [{ required: true, message: "请输入频率惩罚", trigger: "blur" }],
                presence_penalty_test: [{ required: true, message: "请输入存在惩罚", trigger: "blur" }],
                max_tokens_test: [{ required: true, message: "请输入最大令牌数", trigger: "blur" }],
                brand: [{ required: true, message: "请输入内容", trigger: "blur" }],
            },
            rules1: {
                version: [{ required: true, message: "请输入版本号(例:1.0.0)", trigger: "blur" }],
            },
        };
    },
    created() {
        this.getversionList();
    },
    methods: {
         // 上传前验证
         beforeUpload(file) {
            const isPic = file.type.startsWith('image/');
            if (!isPic) {
                this.$message.error('只能上传图片文件！');
                return false;
            }
            const isLimit = file.size / 1024 / 1024 < 5;
            if (!isLimit) {
                this.$message.error('图片不能超过5MB!');
                return false;
            }
            return isPic && isLimit;
        },

        // 选中/移除等变化
        onFileChange(file, fileList) {
            // fileList 中的 raw 为真实 File 对象
            this.imageFileList = fileList;
            this.form.imageFiles = fileList.map(f => f.raw).filter(Boolean);
        },

        removeFile(file, fileList) {
            this.imageFileList = fileList;
            this.form.imageFiles = fileList.map(f => f.raw).filter(Boolean);
        },
         
        validateVersionFormat(version) {
            const regex = /^\d+\.\d+\.\d+$/;
            return regex.test(version);
        },
        openAddVersion() {
            this.dialogVisible1 = true
        },
        async getversionList() {
            this.elloading = this.$loading({
                lock: true,
                text: "Loading",
                spinner: "el-icon-loading",
                background: "rgba(0, 0, 0, 0.7)",
            });
            const { data } = await getImgFoodParseVersionList();
            console.log(data)
            this.queryParams.version = data[data.length - 1].id;
            this.getMore();
            this.versionList = data;
        },
        submitForm1() {
            this.$refs.ruleForm.validate(async (valid) => {
                if (valid) {
                    this.$confirm("确定把配置信息更新到线上吗？", "提示", {
                        confirmButtonText: "确定",
                        cancelButtonText: "取消",
                        type: "error",
                    }).then(async () => {
                        this.elloading = this.$loading({
                            lock: true,
                            text: "Loading",
                            spinner: "el-icon-loading",
                            background: "rgba(0, 0, 0, 0.7)",
                        });
                        await updateImgFoodParseConfig(this.form);
                        await updateImgFoodParseConfigHandel(this.form);
                        this.getMore();
                        this.$message({
                            message: "success!",
                            type: "success",
                        });
                    });
                } else {
                    console.log("提交失败");
                    return false;
                }
            });
        },
        handleClose() {
            this.elloading = this.$loading({
                lock: true,
                text: "Loading",
                spinner: "el-icon-loading",
                background: "rgba(0, 0, 0, 0.7)",
            });
            this.messageRes.content = "";
            this.dialogVisible = false;
            this.getMore();
        },
        handleClose1() {
            this.form1.version = "";
            this.dialogVisible1 = false;
        },
        submitForm() {
            this.bloading = true;
            this.$refs.ruleForm.validate(async (valid) => {
                if (valid) {
                    let res = await updateImgFoodParseConfig(this.form);
                    if (res.code == 0) {
                        this.openAi();
                    }
                } else {
                    console.log("提交失败");
                    return false;
                }
            });
        },

        // openAi 组装
        // AI处理 - 这里示例base64方式
        async openAi() {
            let that = this
            let {
                prompt_test,
                temperature_test,
                max_tokens_test,
                top_p_test,
                frequency_penalty_test,
                top_k_test,
                model_test,
                content,
                imageFiles    // File对象数组
            } = this.form;

            let processedPrompt = prompt_test;
            let messages = [];
            // 加入system消息
            messages.push({
                role: "system",
                content: [{ type: "text", text: processedPrompt }]
            });
            // 将图片转为base64并分别push（OpenAI vision标准API即为base64方式）
            if (imageFiles && imageFiles.length > 0) {
                // 注意：这里是顺次异步处理
                for (let file of imageFiles) {
                    let base64 = await this.fileToBase64(file);
                    messages.push({
                        role: "user",
                        content: [{
                            type: "image_url", // 实际为base64
                            image_url: { url: base64 }
                        }]
                    });
                }
            }
            if (content && content.trim() !== "") {
                messages.push({
                    role: "user",
                    content: [{ type: "text", text: `"output_language"="${content}"` }]
                    
                });
            }
            // 你可以直接传messages，OpenAI vision类API部分支持以base64 data:image/png;base64,...格式的url参数传图
            fetch("https://api-st.siliconflow.cn/v1/chat/completions", {
                method: "POST",
                body: JSON.stringify({
                    model: model_test,
                    messages,
                    stream: true,
                    response_format: { type: "text" },
                    temperature: Number(temperature_test),
                    max_tokens: Number(max_tokens_test),
                    top_p: Number(top_p_test),
                    frequency_penalty: Number(frequency_penalty_test),
                    top_k: Number(top_k_test)
                }),
                headers: {
                    "Content-Type": "application/json",
                    Authorization: `Bearer sk-jwxwusgxhligjvuqchrvjhthmwlnepwwnjyywhtynppwvdpl`
                }
            })
                .then((response) => {
                    this.bloading = false
                    this.messageRes.content = ''
                    this.dialogVisible = true
                    const reader = response.body.getReader();
                    const decoder = new TextDecoder("utf-8"); // 指定解码器为 UTF-8
                    let receivedData = ""; // 累积接收的数据块
                    function processMessages() {
                        const messages = receivedData.split("\n");
                        for (let i = 0; i < messages.length - 1; i++) {
                            const message = messages[i];
                            // 处理完整的消息
                            that.formatDataStr(message, that.handleResult);
                        }
                        // 存储剩余未处理的数据，以便下一次数据块到达时使用
                        receivedData = messages[messages.length - 1];
                    }

                    function read() {
                        return reader.read().then(({ done, value }) => {
                            if (done) {
                                // 接收完成
                                // console.log("接收完所有数据");
                                // 将助手的回复添加到对话中

                                return;
                            }

                            // 累积接收的数据块
                            receivedData += decoder.decode(value);

                            // 检查是否有完整的消息
                            if (receivedData.includes("\n")) {
                                processMessages();
                            }

                            // 继续读取下一个数据块
                            return read();
                        });
                    }
                    return read();
                })
                .catch((error) => {
                    console.log(error);
                    if (error.name === "AbortError") {
                        // console.log("请求被中断");
                    } else {
                        this.bloading = false
                        this.$message.error('请刷新重试！');
                        console.error("请求出错:", error);
                    }
                });
        },

        // 工具：File对象转base64
        fileToBase64(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = e => resolve(e.target.result);
                reader.onerror = err => reject(err);
            });
        },

        handleResult(result) {
            this.$set(this.messageRes, "content", this.messageRes.content + result);
        },
        formatDataStr(str, callback) {
            str.split("\n").forEach((line) => {
                if (line.trim().length > 20) {
                    line.split("data:").forEach((dataSection) => {
                        if (dataSection.trim().length > 10) {
                            const dataObject = JSON.parse(dataSection.trim());
                            if (dataObject.choices[0].delta.content) {
                                callback(dataObject.choices[0].delta.content);
                            }
                        }
                    });
                }
            });
        },
        async getMore() {
            let { data } = await getImgFoodParseConfig(this.queryParams);
            this.imageFileList=[]
            this.form = { ...data, brand: "", imageFiles:[] };
            this.elloading.close();
        },
        handleQuery() {
            this.queryParams.page = 1;
            this.getMore();
        },
        async affirm() {
            this.$refs["ruleForm1"].validate(async (valid) => {
                if (!valid) return;
                this.addLoading = true;
                this.form1.version = this.form1.version.trim();
                if (!this.validateVersionFormat(this.form1.version)) {
                    this.addLoading = false;
                    this.$message.error("版本号格式不正确，应为 x.y.z");
                    return;
                }
                const res = await addImgFoodParseVersion(this.form1);
                if (res.code != 0) {
                    this.$message.error(res.msg);
                } else {
                    this.elloading = this.$loading({
                        lock: true,
                        text: "Loading",
                        spinner: "el-icon-loading",
                        background: "rgba(0, 0, 0, 0.7)",
                    });
                    this.queryParams.version = this.form1.version.trim();
                    this.getversionList();
                    this.$message.success("success");
                }
                this.form1.version = "";
                this.addLoading = false;
                this.dialogVisible1 = false;
            });
        }
    },
};
</script>

<style lang="scss" scoped>
.boxs {
    padding: 20px;
}

::v-deep .el-dialog__body {
    padding: 0;
}

::v-deep .vuepress-markdown-body:not(.custom) {
    padding: 20px;
}
</style>
